package com.ruoyi.merchant.service.impl;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.merchant.domain.FinancialFlow;
import com.ruoyi.merchant.domain.MerchantBankCard;
import com.ruoyi.merchant.domain.dto.FlowQueryDTO;
import com.ruoyi.merchant.domain.dto.WithdrawDTO;
import com.ruoyi.merchant.domain.dto.WithdrawQueryDTO;
import com.ruoyi.merchant.domain.vo.*;
import com.ruoyi.merchant.enums.BusinessTypeEnum;
import com.ruoyi.merchant.enums.FlowTypeEnum;
import com.ruoyi.merchant.enums.PaymentMethodEnum;
import com.ruoyi.merchant.enums.WithdrawalStatusEnum;
import com.ruoyi.merchant.mapper.FinancialFlowMapper;
import com.ruoyi.merchant.mapper.MerchantBankCardMapper;
import com.ruoyi.merchant.service.IMerchantFinanceService;
import com.ruoyi.merchant.utils.MerchantSecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 商家财务Service业务层处理
 */
@Service
public class MerchantFinanceServiceImpl implements IMerchantFinanceService {
    
    @Autowired
    private FinancialFlowMapper financialFlowMapper;

    @Autowired
    private MerchantBankCardMapper merchantBankCardMapper;
    
    /**
     * 查询账户余额
     *
     * @return 账户余额信息
     */
    @Override
    public AccountBalanceVO getAccountBalance() {
        // 获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }
        
        // 查询余额
        BigDecimal balance = financialFlowMapper.selectMerchantBalance(merchantId);
        if (balance == null) {
            throw new ServiceException("商家信息不存在");
        }
        
        // 查询商家名称
        String merchantName = financialFlowMapper.selectMerchantName(merchantId);
        
        // 查询累计收入和支出
        BigDecimal totalIncome = financialFlowMapper.selectTotalIncome(merchantId);
        BigDecimal totalExpense = financialFlowMapper.selectTotalExpense(merchantId);
        
        // 构建返回结果
        AccountBalanceVO vo = new AccountBalanceVO();
        vo.setMerchantId(merchantId);
        vo.setMerchantName(merchantName);
        vo.setBalance(balance);
        vo.setFrozenAmount(BigDecimal.ZERO); // TODO: 预留，后续实现冻结金额功能
        vo.setAvailableBalance(balance); // 当前可用余额 = 余额 - 冻结金额
        vo.setTotalIncome(totalIncome != null ? totalIncome : BigDecimal.ZERO);
        vo.setTotalExpense(totalExpense != null ? totalExpense : BigDecimal.ZERO);
        vo.setUpdateTime(new Date());
        
        return vo;
    }
    
    /**
     * 查询流水列表
     *
     * @param query 查询条件
     * @return 流水列表
     */
    @Override
    public List<FlowListVO> getFlowList(FlowQueryDTO query) {
        // 获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }
        
        // 设置商家ID到查询条件
        query.setMerchantId(merchantId);
        
        // 查询流水列表
        return financialFlowMapper.selectFlowList(query);
    }
    
    /**
     * 查询流水详情
     *
     * @param flowId 流水ID
     * @return 流水详情
     */
    @Override
    public FlowDetailVO getFlowDetail(Long flowId) {
        // 获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }
        
        // 查询流水详情
        FinancialFlow flow = financialFlowMapper.selectFlowById(flowId, merchantId);
        if (flow == null) {
            throw new ServiceException("流水记录不存在");
        }
        
        // 转换为VO
        FlowDetailVO vo = new FlowDetailVO();
        BeanUtils.copyProperties(flow, vo);
        
        // 设置枚举描述
        vo.setFlowTypeName(FlowTypeEnum.getDescByCode(flow.getFlowType()));
        vo.setBusinessTypeName(BusinessTypeEnum.getDescByCode(flow.getBusinessType()));
        vo.setPaymentMethodName(PaymentMethodEnum.getDescByCode(flow.getPaymentMethod()));
        vo.setWithdrawalStatusName(WithdrawalStatusEnum.getDescByCode(flow.getWithdrawalStatus()));
        
        return vo;
    }
    
    /**
     * 提现申请
     *
     * @param withdrawDTO 提现信息
     * @return 提现结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public WithdrawResultVO applyWithdraw(WithdrawDTO withdrawDTO) {
        // 获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }

        // 验证银行卡是否存在且可用
        MerchantBankCard bankCard = merchantBankCardMapper.selectBankCardById(
                withdrawDTO.getWithdrawalCardId(),
                merchantId
        );
        if (bankCard == null) {
            throw new ServiceException("银行卡不存在");
        }
        if (bankCard.getStatus() != 1) {
            throw new ServiceException("银行卡状态异常，无法提现");
        }
        if (bankCard.getIsVerified() != 1) {
            throw new ServiceException("银行卡未验证，请先完成验证");
        }
        
        // 查询当前余额
        BigDecimal currentBalance = financialFlowMapper.selectMerchantBalance(merchantId);
        if (currentBalance == null) {
            throw new ServiceException("商家信息不存在");
        }
        
        // 校验余额是否充足
        if (currentBalance.compareTo(withdrawDTO.getAmount()) < 0) {
            throw new ServiceException("余额不足，当前可用余额：" + currentBalance);
        }
        
        // 校验最小提现金额（可配置）
        BigDecimal minWithdrawAmount = new BigDecimal("0.01");
        if (withdrawDTO.getAmount().compareTo(minWithdrawAmount) < 0) {
            throw new ServiceException("提现金额不能小于" + minWithdrawAmount);
        }

        
        // 生成流水号
        String flowNo = generateFlowNo();
        
        // 计算变动后余额
        BigDecimal balanceAfter = currentBalance.subtract(withdrawDTO.getAmount());
        
        // 创建流水记录
        FinancialFlow flow = new FinancialFlow();
        flow.setFlowNo(flowNo);
        flow.setMerchantId(merchantId);
        flow.setFlowType(FlowTypeEnum.EXPENSE.getCode());
        flow.setBusinessType(BusinessTypeEnum.WITHDRAW.getCode());
        flow.setAmount(withdrawDTO.getAmount());
        flow.setBalanceBefore(currentBalance);
        flow.setBalanceAfter(balanceAfter);
        flow.setCommissionAmount(BigDecimal.ZERO);
        flow.setActualAmount(withdrawDTO.getAmount());
        flow.setWithdrawalCardId(withdrawDTO.getWithdrawalCardId());
        flow.setWithdrawalStatus(WithdrawalStatusEnum.APPLYING.getCode()); // 申请中
        flow.setRemark(withdrawDTO.getRemark());
        flow.setOperatorType(2); // 商家操作
        flow.setOperatorId(merchantId);
        flow.setReviewStatus(0); // 无需审核（模拟场景）
        
        // TODO: 真实场景需要设置结算日期
        // flow.setSettlementDate(calculateSettlementDate());
        
        // 插入流水记录
        int rows = financialFlowMapper.insertFlow(flow);
        if (rows == 0) {
            throw new ServiceException("提现申请失败");
        }
        
        // 更新商家余额（使用乐观锁）
        int updateRows = financialFlowMapper.updateMerchantBalance(
            merchantId, 
            withdrawDTO.getAmount().negate(), // 负数表示减少
            currentBalance
        );
        if (updateRows == 0) {
            throw new ServiceException("余额更新失败，请重试");
        }
        merchantBankCardMapper.updateLastUsedAt(withdrawDTO.getWithdrawalCardId());
        
        // TODO: 模拟场景直接设置为成功，真实场景需要异步处理
        // 模拟：3秒后自动成功
        simulateWithdrawProcess(flow.getFlowId());
        
        // 构建返回结果
        WithdrawResultVO vo = new WithdrawResultVO();
        vo.setFlowId(flow.getFlowId());
        vo.setFlowNo(flow.getFlowNo());
        vo.setAmount(withdrawDTO.getAmount());
        vo.setWithdrawalStatus(WithdrawalStatusEnum.APPLYING.getCode());
        vo.setWithdrawalStatusName(WithdrawalStatusEnum.APPLYING.getDesc());
        
        // 预计到账时间（模拟：1个工作日后）
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 18);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        vo.setEstimatedArrivalTime(calendar.getTime());
        
        return vo;
    }

    /**
     * 查询提现记录列表
     *
     * @param query 查询条件
     * @return 提现记录列表
     */
    @Override
    public List<WithdrawRecordVO> getWithdrawList(WithdrawQueryDTO query) {
        // 获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }

        // 设置商家ID到查询条件
        query.setMerchantId(merchantId);

        // 查询提现记录列表
        return financialFlowMapper.selectWithdrawList(query);
    }
    
    /**
     * 生成流水号
     * 格式：FL + yyyyMMddHHmmss + 3位随机数
     *
     * @return 流水号
     */
    private String generateFlowNo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String datePart = sdf.format(new Date());
        int random = (int) (Math.random() * 900) + 100;
        return "FL" + datePart + random;
    }
    
    /**
     * 模拟提现处理（真实场景应该是异步处理或定时任务）
     *
     * @param flowId 流水ID
     */
    private void simulateWithdrawProcess(Long flowId) {
        // TODO: 真实场景：
        // 1. 发送到消息队列
        // 2. 调用第三方支付接口
        // 3. 回调更新状态
        
        // 模拟场景：直接更新为成功（实际应该由定时任务或回调处理）
        new Thread(() -> {
            try {
                Thread.sleep(3000); // 模拟处理耗时
                financialFlowMapper.updateFlowWithdrawalStatus(
                    flowId, 
                    WithdrawalStatusEnum.SUCCESS.getCode()
                );
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
}
